package com.kasinf.sample.excel.config;

import cn.hutool.core.util.StrUtil;
import cn.idev.excel.context.AnalysisContext;
import cn.idev.excel.event.AnalysisEventListener;
import cn.idev.excel.exception.ExcelDataConvertException;
import com.kasinf.framework.common.util.json.JsonUtils;
import com.kasinf.framework.common.util.string.StreamUtils;
import com.kasinf.framework.common.util.validation.ValidationUtils;
import com.kasinf.framework.excel.core.define.DefaultExcelResult;
import com.kasinf.framework.excel.core.define.ExcelListener;
import com.kasinf.framework.excel.core.define.ExcelResult;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 测试excel工具类
 *
 * @Author : Kaiser
 * @Date: 2025/5/15  15:58
 */
@Slf4j
public class TestExcelListener<TestEntity> extends AnalysisEventListener<TestEntity> implements ExcelListener<TestEntity> {
    /**
     * 批次大小
     */
    private final static Integer BATCH_SIZE = 10;
    /**
     * 导入结果
     */
    private final ExcelResult<TestEntity> excelResult = new DefaultExcelResult<>();
    /**
     * 存放一个批次的数据
     */
    private final List<TestEntity> dataList = new ArrayList<>(BATCH_SIZE);
    /**
     * excel 表头数据
     */
    private Map<Integer, String> headMap;


    @Override
    public ExcelResult<TestEntity> getExcelResult() {
        return excelResult;
    }

    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        this.headMap = headMap;
        log.debug("解析到一条表头数据: {}", JsonUtils.toJsonString(headMap));
    }

    @Override
    public void onException(Exception exception, AnalysisContext context) {
        String errMsg = null;
        if (exception instanceof ExcelDataConvertException excelDataConvertException) {
            // 如果是某一个单元格的转换异常 能获取到具体行号
            Integer rowIndex = excelDataConvertException.getRowIndex();
            Integer columnIndex = excelDataConvertException.getColumnIndex();
            errMsg = StrUtil.format("第{}行-第{}列-表头{}: 解析异常<br/>",
                    rowIndex + 1, columnIndex + 1, headMap.get(columnIndex));
            if (log.isDebugEnabled()) {
                log.error(errMsg);
            }
        }
        if (exception instanceof ConstraintViolationException constraintViolationException) {
            Set<ConstraintViolation<?>> constraintViolations = constraintViolationException.getConstraintViolations();
            String constraintViolationsMsg = StreamUtils.join(constraintViolations, ConstraintViolation::getMessage, ", ");
            errMsg = StrUtil.format("第{}行数据校验异常: {}", context.readRowHolder().getRowIndex() + 1, constraintViolationsMsg);
            if (log.isDebugEnabled()) {
                log.error(errMsg);
            }
        }
        excelResult.getErrorList().add(errMsg);
    }

    @Override
    public void invoke(TestEntity data, AnalysisContext context) {
        // 1. 先校验
        ValidationUtils.validate(data);
        // 2. 将数据加入到批次中
        dataList.add(data);
        // 3. 如果批次满了就保存
        if (dataList.size() >= BATCH_SIZE) {
            saveData();
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 保存剩余的数据
        saveData();
    }

    private void saveData() {
        log.info(">>>> 保存数据....");
        dataList.clear();
    }
}
